package com.process.filter;


import com.common.util.RedisUtil;
import com.system.dto.UserDto;
import com.system.util.JWTUtils;
import org.springframework.security.authentication.AccountExpiredException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;

import static com.system.config.Constants.TOKEN_List;


/**
 * 在SprigSecurity校验登陆前解析Token放入SecurityContext
 */
@Component
public class TokenAuthorizationFilter extends OncePerRequestFilter {

    private final static String AUTHORIZATION_HEADER = "Authorization";

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {

        String token = request.getHeader(AUTHORIZATION_HEADER);
        //没有Authorization header直接跳过
        if (ObjectUtils.isEmpty(token)) {
            filterChain.doFilter(request, response);
            return;
        }
        //将token中的用户名和权限用户组放入Authentication对象,在之后实现鉴权
        if(StringUtils.hasLength(token)&& ObjectUtils.isEmpty(SecurityContextHolder.getContext().getAuthentication())) {
            UserDto userDto= JWTUtils.verify(token.replace("Bearer ", ""));
            Set<String> cacheList = RedisUtil.getCacheObject(String.format(TOKEN_List, userDto.getId()));
            if(!CollectionUtils.isEmpty(cacheList)){//如果用户权限过期
                SecurityContextHolder.getContext().setAuthentication(getAuthentication(userDto,cacheList));
            }
        }
        filterChain.doFilter(request, response);
    }

    //解析token获取用户信息
    private UsernamePasswordAuthenticationToken getAuthentication( UserDto userDto,Set<String> cacheList) throws IOException {
        List<SimpleGrantedAuthority> authorities = new ArrayList<>();
        if(!CollectionUtils.isEmpty(cacheList)) {
            for (String key : cacheList) {
                authorities.add(new SimpleGrantedAuthority(key));
            }
            RedisUtil.expire(String.format(TOKEN_List, userDto.getId()),3600l, TimeUnit.SECONDS);
        }else{
            throw new AccountExpiredException("账号身份已过期，请重新登录。");

        }
        return new UsernamePasswordAuthenticationToken(userDto, null,authorities );
    }

}
